package com.bluedot.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bluedot.controller.DistributeClass;
import com.bluedot.pojo.pack.PreMappedStatement;
import com.bluedot.pojo.pack.ResultEntity;
import com.bluedot.pojo.po.RoleDTO;
import com.bluedot.pojo.vo.PermissionsVO;
import com.bluedot.pojo.vo.RoleVO;
import com.bluedot.pojo.vo.UserVO;
import com.bluedot.utils.OSSProperties;
import com.bluedot.utils.OssUtil;
import io.jsonwebtoken.Claims;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.http.Part;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 用户业务类
 * @author chenzou'quan
 */
public class UserService extends DistributeClass {
    private UtilTool util;
    private UserVO userVO;
    public UserService(PreMappedStatement param) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        super(param);
        this.util = new UtilTool();
        String[] split = preMappedStatement.getMethodType().split("/");
        switch (split[split.length - 1]){
            case "login":
                this.userVO = (UserVO) preMappedStatement.getData();
                UserVO userVO = userLogin();
                break;
            case "list":
                updateList();
                break;
            case "forgetPassword":
                forgetPassword();
                break;
            case "avatar":
                try {
                    avatar();
                } catch (ServletException | IOException e) {
                    throw new RuntimeException(e);
                }
            case "getInfo":
                getInfo();
                break;
            case "add":
                insert();
                break;
            default:
                break;
        }
    }

    /**
     * 修改用户头像
     */
    private  void avatar() throws ServletException, IOException {
        // 1. 获取用户
        UserVO userVo = (UserVO) preMappedStatement.getData();
        // 2. 修改用户
        boolean update = util.update(new PreMappedStatement<>(UtilTool.UPDATE, userVo));
        // 3. 返回结果
        // 3.1 返回失败信息
        if (!update){
            throw new RuntimeException("头像修改失败");
        }
    }

    /**
     * 用户忘记密码
     */
    private  void forgetPassword() {
        UserVO data = (UserVO) preMappedStatement.getData();
        // 1. 获取新密码
        String userPassword = data.getUserPassword();
        data.setUserPassword(null);
        // 2. 查询目标用户
        List<Object> query = util.query(new PreMappedStatement<>(UtilTool.QUERY, data));
        if (query == null){
            getResponseQueue().add(ResultEntity.falseWithoutData("账号错误"));
            return;
        }
        // 3.获取新目标值
        UserVO target = (UserVO) query.get(0);
        // 4.设置新密码
        target.setUserPassword(userPassword);
        boolean update = util.update(new PreMappedStatement<>(UtilTool.UPDATE, target));
        if (!update){
            getResponseQueue().add(ResultEntity.falseWithoutData("修改错误"));
        }else {
            getResponseQueue().add(ResultEntity.successWithoutData());
        }
        return;
    }

    /**
     * 批量用户修改方法（逻辑删除）
     */
    private  void updateList() {
        if (util == null){
            util = new UtilTool();
        }
        List<UserVO> data = (List<UserVO>) preMappedStatement.getData();
        if (data == null || data.size() <= 0){
            throw new RuntimeException("用户数组解析错误");
        }
        for (UserVO user: data) {
            boolean update = util.update(new PreMappedStatement<>(UtilTool.UPDATE, user));
            if (!update){
                throw new RuntimeException("用户id："+user.getUserId()+",该用户修改错误");
            }
        }
    }

    /**
     * 用户登录方法
     * @return 返回userVO类
     */
    private  UserVO userLogin() throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
        // 2.获取密码
        String password = userVO.getUserPassword();
        // 3.设置对象密码为空,只通过账号查询
        userVO.setUserPassword(null);
        // 4.根据解析数据查询用户
        List<Object> query = util.query(new PreMappedStatement<>(UtilTool.QUERY, userVO));
        if (query == null){
            getResponseQueue().add(ResultEntity.falseWithoutData("账号错误"));
            return null;
        }else{
            userVO = (UserVO) query.get(0);
        }
        if (userVO.getUserStatus() != 0){
            getResponseQueue().add(ResultEntity.falseWithoutData("账号异常"));
            return null;
        }
        // 5.获取session
        HttpSession session = preMappedStatement.getRequest().getSession();
        // 6.1 查询失败
        if (!userVO.getUserPassword().equals(password)){
            // 获取登录失败次数
            Integer sum = (Integer) session.getAttribute(userVO.getUserEmail());
            // a.如果失败次数没有储存
            if (sum == null){
                session.setAttribute(userVO.getUserEmail(),1);
                getResponseQueue().add(ResultEntity.falseWithoutData("密码错误"));
                // b.如果失败次数超过5次
            } else if (sum >= 5){
                userVO.setUserStatus(1);
                boolean update = update();
                if (!update){
                    throw new RuntimeException("设置用户非法登录失败");
                }
                getResponseQueue().add(ResultEntity.falseWithoutData("用户登录失败次数超过5次，账号封禁"));
                // c.如果失败次数没有超过5次
            } else {
                session.setAttribute(userVO.getUserEmail(),++sum);
                getResponseQueue().add(ResultEntity.falseWithoutData("密码错误"));
            }
            return null;
        // 6.2 查询成功
        }else {
            // a.登录成功，登录失败结果清零
            session.setAttribute(userVO.getUserEmail(),0);
            // b.查询角色
            extracted(userVO);
            // e.把用户放到session中
            session.setAttribute("user",userVO);
            // f.生成token
            Token tokenTool = new Token();
            String token = tokenTool.getToken(userVO);
            if (token != null) {
                getResponseQueue().add(ResultEntity.successWithDataAndToken(userVO,token));
            } else {
                getResponseQueue().add(ResultEntity.falseWithoutData("生成token失败"));
            }
            return userVO;
        }
    }

    /**
     * userVO对象补充方法
     * @param target 目标对象视图
     */
    private  void extracted(UserVO target) {
        if (util == null){
            util = new UtilTool();
        }
        // 添加一个URL队列
        target.setUrls(new ArrayList<>());
        List<Object> queryRole = util.query(new PreMappedStatement<>(UtilTool.QUERY, new RoleVO(target.getUserId())));
        if (queryRole != null){
            // 转换为role队列
            List<RoleVO> roleVOS = new ArrayList<>();
            for (Object tmp: queryRole) {
                RoleVO roleVO = (RoleVO) tmp;
                // c.查询url
                List<Object> permissionsVO = util.query(new PreMappedStatement<>(UtilTool.QUERY, new PermissionsVO(roleVO.getRoleId())));
                if (permissionsVO != null){
                    // 转换为permissionsVO队列
                    List<String> permissionsName = new ArrayList<>();
                    for (Object tmp_: permissionsVO) {
                        PermissionsVO permissions = (PermissionsVO) tmp_;
                        permissionsName.add(permissions.getPermissionsName());
                        target.getUrls().add(permissions.getPermissionsUrl());
                    }
                    roleVO.setPermissions(permissionsName);
                }
                roleVOS.add(roleVO);
            }
            // d.把角色类别放到用户中
            target.setRoles(roleVOS);
        }
    }

    /**
     * 用户注册方法
     * @return 插入是否成功
     */
    @Override
    protected boolean insert() {
        if (util == null){
            util = new UtilTool();
        }
        // 1.先查找所有用户
        List query = util.query(new PreMappedStatement<>(UtilTool.QUERY,new UserVO()));
        if (query == null){
            throw new RuntimeException("插入失败");
        }
        UserVO data = (UserVO) preMappedStatement.getData();
        // 2.获取目标userid
        String userid = null;
            // 2.1 获取当前年月
        SimpleDateFormat sf = new SimpleDateFormat("yyMM");
        String date = sf.format(new Date());
            // 2.2 获取最大id
        for (Object tmp: query) {
            UserVO user = (UserVO) tmp;
            if (user.getUserEmail().equals(data.getUserEmail())){
                throw new RuntimeException("账号重复");
            }
            if (user.getUserId().length()> 4 && user.getUserId().substring(0,4).equals(date)){
                if (userid == null){
                    userid = user.getUserId();
                }else if (Integer.parseInt(user.getUserId()) > Integer.parseInt(userid)){
                    userid = user.getUserId();
                }
            }
        }
        // 如果用户为当前月份第一个用户
        if (userid == null){
            userid = date+"0001";
        }else {
            userid = String.valueOf(Integer.parseInt(userid)+1);
        }
        // 3.完善用户
            // 3.1 设置用户id
        data.setUserId(userid);
            // 3.2 设置用户状态
        if (data.getUserStatus() == null){
            data.setUserStatus(0);
        }
            // 3.3 设置用户默认头像
        if (data.getUserAvatar() == null) {
            data.setUserAvatar("https://wikifile.oss-cn-shenzhen.aliyuncs.com/images/keli.jpg");
        }
        // 3.4 获取用户角色数据
        List jsons = data.getRoles();
        if (jsons != null){
            data.setRoles(null);
        }
        // 4.插入用户数据
        boolean insert = super.insert();
        if (!insert) {
            throw new RuntimeException("插入失败");
        }
        // 5.插入用户角色

        if (jsons == null || jsons.size() <= 0){

            RoleDTO roleDTO = new RoleDTO(userid, 1);
            insert = util.insert(new PreMappedStatement(UtilTool.INSERT, roleDTO));
            if (!insert) {
                throw new RuntimeException("赋予角色失败");
            }

        }else {
            for (Object json: jsons) {
                JSONObject object = (JSONObject) json;
                String roleId = object.getString("roleId");
                RoleDTO roleDTO = new RoleDTO(userid, Integer.parseInt(roleId));
                insert = util.insert(new PreMappedStatement(UtilTool.INSERT, roleDTO));
                if (!insert) {
                    throw new RuntimeException("赋予角色失败");
                }
            }

        }
        return true;
    }

    /**
     * 用户查询方法
     * @return 查询目标列表
     */
    @Override
    protected List query() {
        Object data =  preMappedStatement.getData();
        if (data.getClass() == String.class){
            if (((String)data).length() <= 0){
                preMappedStatement.setData(new UserVO());
            }
        }
        List query = super.query();
        if (query == null){
            getResponseQueue().add(ResultEntity.falseWithoutData("查询失败"));
            return null;
        }
        // 创建userVO队列
        List<UserVO> userVOS = new ArrayList<>();
        for (Object tmp: query) {
            UserVO user = (UserVO) tmp;
            if (user.getUserStatus() == 3){
                continue;
            }
            extracted(user);
            userVOS.add(user);
        }
        getResponseQueue().add(ResultEntity.successWithData(userVOS));
        return userVOS;
    }

    /**
     * 用户修改方法
     * @return 修改是否成功
     */
    @Override
    protected boolean update() {
        if (util == null){
            util = new UtilTool();
        }
        // 1.先修改user基本信息
        UserVO data = (UserVO) preMappedStatement.getData();
        // 1.1获得附加信息
        List jsons = data.getRoles();
        List<RoleVO> roles = new ArrayList<>();
        Map<Integer,Integer> roleId = null;
        if (jsons != null) {
            for (Object json: jsons) {
                if (json.getClass() == Integer.class){
                    RoleVO role = new RoleVO();
                    role.setRoleId((Integer) json);
                    roles.add(role);
                }else {
                    JSONObject object = (JSONObject) json;
                    RoleVO role = new RoleVO();
                    role.setRoleId(Integer.parseInt(object.getString("roleId")));
                    roles.add(role);
                }
            }
            roleId = new HashMap();
            for (RoleVO role: roles) {
                roleId.put(role.getRoleId(),role.getRoleId());
            }
        }
        // 1.2设置附加信息
        data.setRoles(null);
        data.setUrls(null);
        // 1.3修改方法
        boolean update = super.update();
        if (!update){
            throw new RuntimeException("修改用户信息失败");
        }
        if (jsons != null) {
            // 2.修改对应角色
            // 2.1先查找对应角色
            List<Object> query = util.query(new PreMappedStatement<>(UtilTool.QUERY, new RoleDTO(data.getUserId(), null)));
            // 如果没有对应的角色,则全部插入数据库
            if (query == null){
                for (RoleVO role: roles) {
                    boolean insert = util.insert(new PreMappedStatement<>(UtilTool.INSERT, new RoleDTO(data.getUserId(), role.getRoleId())));
                    if (!insert){
                        throw new RuntimeException("修改角色失败");
                    }
                }
            }
            // 如果数据库中存在用户原角色信息
            else {
                for (Object roleTmp: query) {
                    RoleDTO roleDTO = (RoleDTO) roleTmp;
                    // 如果原数据有，更改数据没有
                    if (roleId.get(roleDTO.getRoleId()) == null){
                        boolean delete = util.delete(new PreMappedStatement<>(UtilTool.DELETE,
                                new RoleDTO(data.getUserId(), roleDTO.getRoleId())));
                        if (!delete){
                            throw new RuntimeException("角色信息变更失败");
                        }
                    }
                    // 如果原数据和更新数据都有
                    else {
                        roleId.remove(roleDTO.getRoleId());
                    }
                }
                // 如果原数据没有更新数据有
                Collection<Integer> values = roleId.values();
                for (Integer rId: values) {
                    boolean insert = util.insert(new PreMappedStatement<>(UtilTool.INSERT, new RoleDTO(data.getUserId(), rId)));
                    if (!insert){
                        throw new RuntimeException("修改角色失败");
                    }
                }
            }
        }
        return true;
    }

    /**
     * 用户删除方法
     * @return 删除是否成功
     */
    @Override
    protected boolean delete() {
        if (util == null){
            util = new UtilTool();
        }
        List<UserVO> data = (List<UserVO>) preMappedStatement.getData();
        if (data == null || data.size() <= 0){
            throw new RuntimeException("用户数组解析错误");
        }
        for (UserVO user: data) {
            boolean update = util.delete(new PreMappedStatement<>(UtilTool.DELETE, user));
            if (!update){
                throw new RuntimeException("用户id："+user.getUserId()+",该用户删除错误");
            }
        }
        return true;
    }

    /**
     * 获取用户信息方法
     */
    private void getInfo(){
        // 1.获取token
        HttpServletRequest request = preMappedStatement.getRequest();
        String token = request.getHeader("token");
        // 2.根据token获取Claims
        Claims tokenClaim = new Token().getTokenClaim(token);
        // 3.再获得JSON数据
        String subject = tokenClaim.getSubject();
        Map map = JSONObject.parseObject(subject, Map.class);
        // 4.获得userVo
        UserVO userVO = JSONObject.parseObject(map.get("user").toString(),UserVO.class);
        // 5.写入参数中
        UserVO userVO1 = new UserVO();
        userVO1.setUserId(userVO.getUserId());
        preMappedStatement.setData(userVO1);
        // 6.查询用户
        List<Object> query = util.query(new PreMappedStatement<>(UtilTool.QUERY, userVO1));
        // 创建userVO队列
        List<UserVO> userVOS = new ArrayList<>();
        for (Object tmp: query) {
            UserVO user = (UserVO) tmp;
            extracted(user);
            userVOS.add(user);
        }
        if (userVOS.size() <= 0){
            getResponseQueue().add(ResultEntity.falseWithoutData("未查询到该用户"));
        }else {
            UserVO o = (UserVO) query.get(0);
//            HttpSession session = request.getSession();
//            session.setAttribute("user",o);
            getResponseQueue().add(ResultEntity.successWithData(o));
        }
    }
}
